﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Ors.RInterface.Engine.PInvoke
{
   // /* The standard node structure consists of a header followed by the
   //node data. */
   // typedef struct SEXPREC {
   //     SEXPREC_HEADER;
   //     union {
   //     struct primsxp_struct primsxp;
   //     struct symsxp_struct symsxp;
   //     struct listsxp_struct listsxp;
   //     struct envsxp_struct envsxp;
   //     struct closxp_struct closxp;
   //     struct promsxp_struct promsxp;
   //     } u;
   // } SEXPREC, *SEXP;
    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
    public struct SEXP
    {
        [FieldOffset(0)]
        public SEXP_HEADER header;
        [FieldOffset(16)]
        public PRIMSXP primsxp;
        [FieldOffset(16)]
        public SYMSXP symsxp;
        [FieldOffset(16)]
        public LISTSXP listsxp;
        [FieldOffset(16)]
        public ENVSXP envsxp;
        [FieldOffset(16)]
        public CLOSSXP closxp;
        [FieldOffset(16)]
        public PROMSXP promsxp;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class pSEXP
    {
       
        public static pSEXP FromNative(IntPtr ptr)
        {
            unsafe
            {
                byte* p = (byte*)ptr.ToPointer();
                pSEXP obj = new pSEXP();
                
                obj.header.sxpinfo.type = (SEXPTYPE)(*((uint*)p) & 0x1F);//5
                obj.header.sxpinfo.obj |= *((uint*)p) & 0x20;//1 =6;
                obj.header.sxpinfo.named |= *((uint*)p) & 0xC0;//2 =8;
                obj.header.sxpinfo.gp |= *((uint*)p) & 0xffff00;//16 =24;
                obj.header.sxpinfo.mark |= *((uint*)p) & 0x1000000;//1 =25;
                obj.header.sxpinfo.debug |= *((uint*)p) & 0x2000000;//1 =26;
                obj.header.sxpinfo.trace |= *((uint*)p) & 0x4000000;//1 =27;
                obj.header.sxpinfo.spare |= *((uint*)p) & 0x8000000;//1 =28;
                obj.header.sxpinfo.gcgen |= *((uint*)p) & 0x10000000;//1 =29;
                obj.header.sxpinfo.gccls |= *((uint*)p) & 0xE0000000;//3 =29;
                //address of the attrib sexp
                obj.header.attrib = *(IntPtr*)(p += 4);
                //next
                obj.header.gengc_next_node = *(IntPtr*)(p += 4);
                //prev
                obj.header.gengc_prev_node = *(IntPtr*)(p += 4);
                return obj;
            }
        }

        

        //[FieldOffset(0)]
        public SEXP_HEADER header;
        //[FieldOffset(16)]
        public PRIMSXP primsxp;
        //[FieldOffset(16)]
        public SYMSXP symsxp;
        //[FieldOffset(16)]
        public ENVSXP envsxp;
        //[FieldOffset(16)]
        public CLOSSXP closxp;
        //[FieldOffset(16)]
        public PROMSXP promsxp;
    }
}
